﻿using System;
using System.Collections;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace TSharp.Core.Aop.Handler
{
    /// <summary>
    /// 验证处理类
    /// </summary>
    public class ValidationHandler : ICallHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidationHandler"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="order">The order.</param>
        public ValidationHandler(Type type, int order)
        {
            Type = type;
            Order = order;
        }

        /// <summary>
        /// 验证类型名称
        /// </summary>
        public Type Type { get; set; }

        /// <summary>
        /// 换行符
        /// </summary>
        public static string NewLine { get; set; }

        #region ICallHandler Members

        /// <summary>
        /// Order in which the handler will be executed
        /// </summary>
        /// <value></value>
        public int Order { get; set; }

        /// <summary>
        /// Implement this method to execute your handler processing.
        /// </summary>
        /// <param name="input">Inputs to the current call to the target.</param>
        /// <param name="getNext">Delegate to execute to get the next delegate in the handler
        /// chain.</param>
        /// <returns>Return value from the target.</returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            //验证方法的参数
            PreCall(input);
            //验证目标对象
            if (Type != null)
                Validate(ValidationFactory.CreateValidator(Type), input.Target);
            return getNext()(input, getNext);
        }

        #endregion

        /// <summary>
        /// 方法执行前 验证参数
        /// </summary>
        /// <param name="input">The input.</param>
        private void PreCall(IMethodInvocation input)
        {
            for (int i = 0; i < input.Inputs.Count; ++i)
            {
                object obj = input.Inputs[i];
                var irbl = obj as IEnumerable;
                //如果输入参数是列表
                if (irbl != null)
                {
                    IEnumerator ir = irbl.GetEnumerator();
                    while (ir.MoveNext())
                    {
                        object cur = ir.Current;
                        Validator validator = ValidationFactory.CreateValidator(cur.GetType());
                        Validate(validator, cur);
                    }
                }
                    //字符串则要进行防止sql注入
                else if (obj is string)
                {
                }
                    //排除值类型的验证，
                else if (obj is Nullable)
                {
                    Validator validator = ValidationFactory.CreateValidator(obj.GetType());
                    Validate(validator, obj);
                }
            }
        }

        /// <summary>
        /// 对关键字进行转义
        /// </summary>
        /// <param name="keyword">关键字</param>
        /// <returns>转义后的关键字</returns>
        /// <remarks></remarks>
        public static string EscapeKeyword(string keyword)
        {
            // 注意：不要打乱现有顺序
            keyword = keyword.Replace("'", "''");
            keyword = keyword.Replace("[", "[[]");
            keyword = keyword.Replace("%", "[%]");
            keyword = keyword.Replace("_", "[_]");
            return keyword;
        }

        /// <summary>
        /// Validates the specified validator.
        /// </summary>
        /// <param name="validator">The validator.</param>
        /// <param name="target">The target.</param>
        public void Validate(Validator validator, object target)
        {
            ValidationResults results = validator.Validate(target);
            if (!results.IsValid)
            {
                var sb = new StringBuilder();
                foreach (ValidationResult result in results)
                {
                    sb.Append("关键字 = " + result.Key + NewLine);
                    sb.Append("消息 = " +
                              result.Message + NewLine);
                }
                throw new InvalidOperationException(sb.ToString());
            }
        }
    }
}